/*
 * Copyright (C) 2018 Logos Technology Ltd.
 */

package com.logos.tool.log;

import android.util.Log;

import com.logos.tool.BuildConfig;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;

public class LogUtil {

    private static boolean sIs4Mock;
    private static final int MAX_LENGTH = 4000;

    /**
     * set mock
     *
     * @param forMock bool
     */
    public static void set4Mock(boolean forMock) {
        sIs4Mock = forMock;
    }

    /**
     * 以v标签打印log
     *
     * @param tag 标签
     * @param msg 信息.
     */
    public static void verbose(String tag, String msg) {
        if (sIs4Mock) {
            return;
        }

        if (BuildConfig.DEBUG) {
            printDefault(Log.VERBOSE, tag, getStackTrace() + ": " + msg);
        }
    }

    /**
     * 以d标签打印log
     *
     * @param tag 标签
     * @param msg 信息.
     */
    public static void debug(String tag, String msg) {
        if (sIs4Mock) {
            return;
        }

        if (BuildConfig.DEBUG) {
            printDefault(Log.DEBUG, tag, getStackTrace() + ": " + msg);
        }
    }

    /**
     * 以i标签打印log
     *
     * @param tag 标签
     * @param msg 信息.
     */
    public static void info(String tag, String msg) {
        if (sIs4Mock) {
            return;
        }

        if (BuildConfig.DEBUG) {
            printDefault(Log.INFO, tag, getStackTrace() + ": " + msg);
        }
    }

    /**
     * 以w标签打印log
     *
     * @param tag 标签
     * @param msg 信息.
     */
    public static void warn(String tag, String msg) {
        if (sIs4Mock) {
            return;
        }

        if (BuildConfig.DEBUG) {
            printDefault(Log.WARN, tag, getStackTrace() + ": " + msg);
        }
        DiskLog.getInstance().log(Log.WARN, tag, tag + ": " + msg);
    }

    /**
     * 以e标签打印log
     *
     * @param tag 标签
     * @param msg 信息.
     */
    public static void error(String tag, String msg) {
        if (sIs4Mock) {
            return;
        }

        if (BuildConfig.DEBUG) {
            printDefault(Log.ERROR, tag, getStackTrace() + ": " + msg);
        }
        DiskLog.getInstance().log(Log.ERROR, tag, tag + ": " + msg);
    }

    /**
     * 以e标签打印log
     *
     * @param tag       标签
     * @param msg       信息.
     * @param throwable Throwable
     */
    public static void error(String tag, String msg, Throwable throwable) {
        if (sIs4Mock) {
            return;
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        throwable.printStackTrace(ps);

        if (BuildConfig.DEBUG) {
            printDefault(Log.ERROR, tag, getStackTrace() + ": " + msg);
            printDefault(Log.ERROR, tag, getStackTrace() + ": " + baos.toString());
        }
        DiskLog.getInstance().log(Log.ERROR, tag, tag + ": " + msg);
    }

    /**
     * getStackTrace
     *
     * @param throwable throwable
     * @return str
     */
    public static String getStackTrace(Throwable throwable) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            throwable.printStackTrace(pw);
            return sw.toString();
        } finally {
            pw.close();
        }
    }

    private static String getStackTrace() {
        StackTraceElement[] stackTraceElement = Thread.currentThread().getStackTrace();
        int currentIndex = -1;
        for (int i = 0; i < stackTraceElement.length; i++) {
            if (stackTraceElement[i].getClassName()
                    .compareTo("com.logos.tool.log.LogUtil") == 0) {
                currentIndex = i + 2;
                break;
            }
        }

        String fileName = stackTraceElement[currentIndex].getFileName();
        String methodName = stackTraceElement[currentIndex].getMethodName();
        String lineNumber = String.valueOf(stackTraceElement[currentIndex].getLineNumber());

        String info = methodName + " (" + fileName + ":" + lineNumber + ")";
        return "";
    }

    /**
     * 输出日志
     *
     * @param type type
     * @param tag  tag
     * @param msg  msg
     */
    private static void printDefault(int type, String tag, String msg) {

        int index = 0;
        int length = msg.length();
        int countOfSub = length / MAX_LENGTH;

        if (countOfSub > 0) {
            for (int i = 0; i < countOfSub; i++) {
                String sub = msg.substring(index, index + MAX_LENGTH);
                printSub(type, tag, sub);
                index += MAX_LENGTH;
            }
            printSub(type, tag, msg.substring(index, length));
        } else {
            printSub(type, tag, msg);
        }
    }

    private static void printSub(int type, String tag, String sub) {
        switch (type) {
            case Log.VERBOSE:
                Log.v(tag, sub);
                break;
            case Log.DEBUG:
                Log.d(tag, sub);
                break;
            case Log.INFO:
                Log.i(tag, sub);
                break;
            case Log.WARN:
                Log.w(tag, sub);
                break;
            case Log.ERROR:
                Log.e(tag, sub);
                break;
            case Log.ASSERT:
                Log.wtf(tag, sub);
                break;
            default:
                break;
        }
    }

}
